﻿/*****************************************介绍*****************************************
 * 作者：Ywh
 * 创建时间：2023-03-25　04:42:26
 * 功能：需要序列化和反序列化的数据模型基类
 *      1、需要自己去实现子类的序列化和反序列化
**************************************************************************************/

#define HANDLING_BYTE_ORDER
#undef HANDLING_BYTE_ORDER

using System;
using System.Text;
using UnityEngine;

namespace Game.Framework.Utility
{
    public abstract class DataBase
    {
        public abstract int GetByteNumber();

        /// <summary>反序列化</summary>
        /// <returns>返回当前数据模型所占的内存大小（单位 bit）</returns>
        public virtual int Deserialize(byte[] buffer, int offset = 0)
        {
            throw new NotImplementedException("未实现该功能");
        }

        public virtual byte[] Serialize()
        {
            throw new NotImplementedException("未实现该功能");
        }

        #region 读取
        protected bool ReadBool(byte[] buffer, ref int offset)
        {
            var result = BitConverter.ToBoolean(buffer, offset);
            offset += 1;
            return result;
        }

        protected byte ReadByte(byte[] buffer, ref int offset)
        {
            return buffer[offset++];
        }

        protected char ReadChar(byte[] buffer, ref int offset)
        {
#if HANDLING_BYTE_ORDER
            if (BitConverter.IsLittleEndian)
                Array.Reverse(buffer, offset, 2);
#endif
            var result = BitConverter.ToChar(buffer, offset);
            offset += 2;
            return result;
        }

        protected ushort ReadUInt16(byte[] buffer, ref int offset)
        {
#if HANDLING_BYTE_ORDER
            if (BitConverter.IsLittleEndian)
                Array.Reverse(buffer, offset, 2);
#endif
            var result = BitConverter.ToUInt16(buffer, offset);
            offset += 2;
            return result;
        }

        protected short ReadInt16(byte[] buffer, ref int offset)
        {
#if HANDLING_BYTE_ORDER
            if (BitConverter.IsLittleEndian)
                Array.Reverse(buffer, offset, 2);
#endif
            var result = BitConverter.ToInt16(buffer, offset);
            offset += 2;
            return result;
        }

        protected uint ReadUInt32(byte[] buffer, ref int offset)
        {
#if HANDLING_BYTE_ORDER
            if (BitConverter.IsLittleEndian)
                Array.Reverse(buffer, offset, 4);
#endif
            var result = BitConverter.ToUInt32(buffer, offset);
            offset += 4;
            return result;
        }

        protected int ReadInt32(byte[] buffer, ref int offset)
        {
#if HANDLING_BYTE_ORDER
            if (BitConverter.IsLittleEndian)
                Array.Reverse(buffer, offset, 4);
#endif
            var result = BitConverter.ToInt32(buffer, offset);
            offset += 4;
            return result;
        }

        protected ulong ReadUInt64(byte[] buffer, ref int offset)
        {
#if HANDLING_BYTE_ORDER
            if (BitConverter.IsLittleEndian)
                Array.Reverse(buffer, offset, 8);
#endif
            var result = BitConverter.ToUInt32(buffer, offset);
            offset += 8;
            return result;
        }

        protected long ReadInt64(byte[] buffer, ref int offset)
        {
#if HANDLING_BYTE_ORDER
            if (BitConverter.IsLittleEndian)
                Array.Reverse(buffer, offset, 8);
#endif
            var result = BitConverter.ToInt32(buffer, offset);
            offset += 8;
            return result;
        }

        protected float ReadSingle(byte[] buffer, ref int offset)
        {
#if HANDLING_BYTE_ORDER
            if (BitConverter.IsLittleEndian)
                Array.Reverse(buffer, offset, 4);
#endif
            var result = BitConverter.ToSingle(buffer, offset);
            offset += 4;
            return result;
        }

        protected double ReadDouble(byte[] buffer, ref int offset)
        {
#if HANDLING_BYTE_ORDER
            if (BitConverter.IsLittleEndian)
                Array.Reverse(buffer, offset, 8);
#endif
            var result = BitConverter.ToDouble(buffer, offset);
            offset += 8;
            return result;
        }

        protected string ReadString(byte[] buffer, ref int offset)
        {
            int byteLength = ReadInt32(buffer, ref offset);
            var result = Encoding.UTF8.GetString(buffer, offset, byteLength);
            offset += byteLength;
            return result;
        }

        protected Vector2 ReadVector2(byte[] buffer, ref int offset)
        {
            float x = ReadSingle(buffer, ref offset);
            float y = ReadSingle(buffer, ref offset);
            return new Vector2(x, y);
        }

        protected Vector3 ReadVector3(byte[] buffer, ref int offset)
        {
            float x = ReadSingle(buffer, ref offset);
            float y = ReadSingle(buffer, ref offset);
            float z = ReadSingle(buffer, ref offset);
            return new Vector3(x, y, z);
        }

        protected Quaternion ReadQuaternion(byte[] buffer, ref int offset)
        {
            float x = ReadSingle(buffer, ref offset);
            float y = ReadSingle(buffer, ref offset);
            float z = ReadSingle(buffer, ref offset);
            float w = ReadSingle(buffer, ref offset);
            return new Quaternion(x, y, z, w);
        }

        protected T ReadData<T>(byte[] buffer, ref int offset) where T : DataBase, new()
        {
            T result = new T();
            int byteLength = result.Deserialize(buffer, offset);
            offset += byteLength;
            return result;
        }
        #endregion

        #region 写入
        protected void WriteBool(bool value, byte[] buffer, ref int offset)
        {
            BitConverter.GetBytes(value).CopyTo(buffer, offset);
            offset += 1;
        }

        protected void WriteByte(byte value, byte[] buffer, ref int offset)
        {
            buffer[offset++] = value;
        }

        protected void WriteChar(char value, byte[] buffer, ref int offset)
        {
            BitConverter.GetBytes(value).CopyTo(buffer, offset);
            offset += 2;
        }

        protected void WriteUInt16(ushort value, byte[] buffer, ref int offset)
        {
            BitConverter.GetBytes(value).CopyTo(buffer, offset);
            offset += 2;
        }

        protected void WriteInt16(short value, byte[] buffer, ref int offset)
        {
            BitConverter.GetBytes(value).CopyTo(buffer, offset);
            offset += 2;
        }

        protected void WriteUInt32(uint value, byte[] buffer, ref int offset)
        {
            BitConverter.GetBytes(value).CopyTo(buffer, offset);
            offset += 4;
        }

        protected void WriteInt32(int value, byte[] buffer, ref int offset)
        {
            BitConverter.GetBytes(value).CopyTo(buffer, offset);
            offset += 4;
        }

        protected void WriteUInt64(ulong value, byte[] buffer, ref int offset)
        {
            BitConverter.GetBytes(value).CopyTo(buffer, offset);
            offset += 8;
        }

        protected void WriteInt64(long value, byte[] buffer, ref int offset)
        {
            BitConverter.GetBytes(value).CopyTo(buffer, offset);
            offset += 8;
        }

        protected void WriteSingle(float value, byte[] buffer, ref int offset)
        {
            BitConverter.GetBytes(value).CopyTo(buffer, offset);
            offset += 4;
        }

        protected void WriteDouble(double value, byte[] buffer, ref int offset)
        {
            BitConverter.GetBytes(value).CopyTo(buffer, offset);
            offset += 8;
        }

        protected void WriteString(string value, byte[] buffer, ref int offset)
        {
            int byteLength = Encoding.UTF8.GetByteCount(value);
            WriteInt32(byteLength, buffer, ref offset);
            Encoding.UTF8.GetBytes(value).CopyTo(buffer, offset);
            offset += byteLength;
        }

        protected void WriteVector2(Vector2 value, byte[] buffer, ref int offset)
        {
            WriteSingle(value.x, buffer, ref offset);
            WriteSingle(value.y, buffer, ref offset);
        }

        protected void WriteVector3(Vector3 value, byte[] buffer, ref int offset)
        {
            WriteSingle(value.x, buffer, ref offset);
            WriteSingle(value.y, buffer, ref offset);
            WriteSingle(value.z, buffer, ref offset);
        }

        protected void WriteQuaternion(Quaternion value, byte[] buffer, ref int offset)
        {
            WriteSingle(value.x, buffer, ref offset);
            WriteSingle(value.y, buffer, ref offset);
            WriteSingle(value.z, buffer, ref offset);
            WriteSingle(value.w, buffer, ref offset);
        }

        protected void WriteData<T>(T value, byte[] buffer, ref int offset) where T : DataBase, new()
        {
            int byteLength = value.GetByteNumber();
            value.Serialize().CopyTo(buffer, offset);
            offset += byteLength;
        }
        #endregion
    }
}
